﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web;
using System.Data;
using System.IO;
using System.Reflection;
using System.Linq;
using Anthony.Library.Entensions;

namespace Anthony.Library
{
    /// <summary>
    /// Utility class to change the current response to output files
    /// </summary>
    public static class FileResponse
    {

        /// <summary>
        /// Outputs a file to the response stream. Used for force downloads.
        /// </summary>
        /// <param name="CallingPage"></param>
        /// <param name="fi"></param>
        public static void OutputFile(FileInfo fi)
        {
            if (!fi.Exists)
                throw new Exception("Could not find file referenced");

            //open file
            FileStream fs = fi.OpenRead();

            //configure header info
            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.Buffer = true;
            HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fi.Name + "\"");
            HttpContext.Current.Response.AddHeader("Content-Length", fi.Length.ToString());
            HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
            HttpContext.Current.Response.Charset = "";
            switch (fi.Extension)
            {
                case ".asf":
                    HttpContext.Current.Response.ContentType = "video/x-ms-asf";
                    break;
                case ".avi":
                    HttpContext.Current.Response.ContentType = "video/avi";
                    break;
                case ".doc":
                    HttpContext.Current.Response.ContentType = "application/msword";
                    break;
                case ".zip":
                    HttpContext.Current.Response.ContentType = "application/zip";
                    break;
                case ".xls":
                    HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
                    break;
                case ".gif":
                    HttpContext.Current.Response.ContentType = "image/gif";
                    break;
                case ".jpg":
                    HttpContext.Current.Response.ContentType = "image/jpeg";
                    break;
                case ".jpeg":
                    HttpContext.Current.Response.ContentType = "image/jpeg";
                    break;
                case ".wav":
                    HttpContext.Current.Response.ContentType = "audio/wav";
                    break;
                case ".mp3":
                    HttpContext.Current.Response.ContentType = "audio/mpeg3";
                    break;
                case ".mpg":
                    HttpContext.Current.Response.ContentType = "video/mpeg";
                    break;
                case ".mpeg":
                    HttpContext.Current.Response.ContentType = "video/mpeg";
                    break;
                case ".rtf":
                    HttpContext.Current.Response.ContentType = "application/rtf";
                    break;
                case ".htm":
                    HttpContext.Current.Response.ContentType = "text/html";
                    break;
                case ".html":
                    HttpContext.Current.Response.ContentType = "text/html";
                    break;
                case ".asp":
                    HttpContext.Current.Response.ContentType = "text/asp";
                    break;
                default:
                    //Handle All Other Files
                    HttpContext.Current.Response.ContentType = "application/octet-stream";
                    break;
            }


            byte[] buffer = new byte[(int)fs.Length];
            fs.Read(buffer, 0, (int)fs.Length);
            fs.Close();

            HttpContext.Current.Response.BinaryWrite(buffer);
            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.Close();
        }

        /// <summary>
        /// Calling this method will change the response to return a CSV file of the dataview passed.
        /// </summary>
        /// <param name="dv"></param>
        /// <param name="fileName"></param>
        public static void OutputCSV(DataView dv, string fileName)
        {
            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.Buffer = true;
            HttpContext.Current.Response.ContentType = "text/csv";
            HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".csv\"");
            HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
            HttpContext.Current.Response.Charset = "";
            HttpContext.Current.Response.Write(dv.ToCSV());
            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.Close();
        }


        /// <summary>
        /// Calling this method will change the response to return a CSV file of the IQueryable&lt;T&gt; passed.
        /// </summary>
        /// <typeparam name="T">Type of list item</typeparam>
        /// <param name="list">The list.</param>
        /// <param name="filename">The filename.</param>
        /// <param name="exclude">The exclude.</param>
        public static void OutputCSV<T>(IQueryable<T> list, string filename, params string[] exclude)
        {
            StringWriter sw = new StringWriter();
            bool headerPrinted = false;
            Type type = typeof(T);
            PropertyInfo[] properties = type.GetProperties();
            foreach (var obj in list)
            {
                string s = String.Empty;
                if (!headerPrinted)
                {
                    foreach (PropertyInfo propertyInfo in properties)
                    {
                        if (exclude.Count(x => x.Contains(propertyInfo.Name)) > 0)
                            continue;

                        if (s.Length > 0)
                            s = String.Join(",", new string[] { s, propertyInfo.Name });
                        else
                            s = propertyInfo.Name;
                    }
                    sw.WriteLine(s);
                    headerPrinted = true;
                }

                s = String.Empty;
                for (int idx = 0; idx < properties.Length; idx++)
                {

                    if (exclude.Count(x => x.Contains(properties[idx].Name)) > 0)
                        continue;

                    var value = properties[idx].GetValue(obj, null);
                    var formattedValue = value == null ? String.Empty : value.ToString();

                    if (value != null)
                    {
                        if (value.GetType() == typeof(string))
                            formattedValue = "\"" + formattedValue + "\"";
                    }

                    if (s.Length > 0)
                        s = String.Join(",", new string[] { s, formattedValue });
                    else
                        s = formattedValue;

                }
                sw.WriteLine(s);
            }
            HttpResponse response = System.Web.HttpContext.Current.Response;
            response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
            response.ContentType = "application/ms-excel";
            response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
            response.Write(sw);
            response.End();
        }
	}
}
